#include <iostream>

#include <framework/script.h>
#include <util/gref.h>

#include "components.h"
#include "scripting.h"

static QScriptValue PrintFunction(QScriptContext *context, QScriptEngine *engine)
{
  QString result;

  for (int i = 0; i < context->argumentCount(); ++i)
    result.append(context->argument(i).toString());

  std::cout << result.toStdString();

  return engine->undefinedValue();
}

static void Exit(int code)
{
  QScriptEngine &engine = GRef< ScriptingScope >()->mEngine;

  engine.globalObject().setProperty("ExitCode", code);
  QCoreApplication::exit(code);
}

ScriptingScope::ScriptingScope()
{
  using namespace framework::script;

  mEngine.globalObject().setProperty("print", mEngine.newFunction(PrintFunction));

  // System
  RegisterFunction(mEngine, "Exit", Exit);

  // Scripting
  RegisterFunction(mEngine, "RunCode", RunCode);
  RegisterFunction(mEngine, "RunFile", RunFile);

  // Components
  RegisterFunction(mEngine, "MakeComponent", MakeComponent);
}

ScriptingScope::~ScriptingScope()
{
}

QScriptValue RunCode(const QString & Code_, const QString & FileName_)
{
  QScriptValue val;

  QScriptEngine &engine = GRef< ScriptingScope >()->mEngine;
  val = engine.evaluate(Code_);

  if (engine.hasUncaughtException())
  {
    if (!FileName_.isEmpty())
      std::cout << FileName_.toStdString() << ". ";

    std::cout
      << "exception at line "
      << engine.uncaughtExceptionLineNumber()
      << "; "
      << engine.uncaughtException().toString().toStdString()
      << std::endl;

    engine.abortEvaluation();
  }

  return val;
}

QScriptValue RunFile(const QString & FileName_)
{
  std::cout << "executing: " << FileName_.toStdString() << std::endl;

  QFile f(FileName_);
  
  if (!f.open(QIODevice::ReadOnly))
  {
    std::cout << "unable to open file" << std::endl;
    return QScriptValue();
  }
  QTextStream s(&f);

  return RunCode(s.readAll(), FileName_);
}